package com.starblink.search.result.ui.fragment.goods

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.apollographql.apollo3.api.Optional
import com.starblink.android.basic.data.model.product.ProductFWrap
import com.starblink.android.basic.data.model.product.RecommendProductF
import com.starblink.android.basic.ext.string
import com.starblink.android.basic.extension.apollo.toWrap
import com.starblink.android.basic.extension.lazyOnNone
import com.starblink.android.basic.network.base.SkGqlClient
import com.starblink.basic.apollo.ext.optional
import com.starblink.rocketreserver.FetchRecommendProductCollectionQuery
import com.starblink.rocketreserver.SearchBrandsQuery
import com.starblink.rocketreserver.SearchProductsQuery
import com.starblink.rocketreserver.fragment.BrandVOF
import com.starblink.rocketreserver.type.BrandSearchReq
import com.starblink.rocketreserver.type.ProductQueryParam
import com.starblink.rocketreserver.type.ProductRecommendQueryParam
import com.starblink.search.config.SearchConfig
import com.starblink.search.result.repository.model.DrawerPriceInputModel
import com.starblink.search.result.repository.model.DrawerTitleModel
import com.starblink.search.result.repository.model.GoodsRecommendTileModel
import com.starblink.search.result.repository.model.GoodsResultEmptyModel
import com.starblink.search.result.repository.model.SelectDiscountProperty
import com.starblink.search.result.repository.model.SelectableBrand
import com.starblink.search.result.repository.model.SelectableBrandWrap
import com.starblink.search.result.repository.model.SelectableProperty
import com.starblink.search.result.repository.model.SelectablePropertyWrap
import com.starblink.search.result.ui.fragment.BaseSearchVM
import kotlinx.coroutines.launch

class GoodsResultVM : BaseSearchVM() {

    var scene = SearchConfig.SCENE_ALL

    var recPageNo = 1

    var pageNo = 1

    var queryWord: String = ""//搜索词
    var categoryName: String = ""//类目名称
    var searchWordSource: Int? = null

    var goodsRuleId: String? = null

    var needQueryFilter = false

    var sortType = SearchConfig.SORT_DEFAULT

    /**过滤：Sale*/
    var filterSale: Boolean = false

    /**折扣排序，0-默认排序，1-从大到小，2-从小到大*/
    var saleSort: Int = 0

    /**LiveData:FilterSale是否可见,true可见*/
    val filterSaleVisibleLiveData = MutableLiveData<Boolean>()

    var reqFilterBrands = arrayListOf<String>()

    var reqFilterProperties = arrayListOf<String>()

    var filterLowestPrice: Double? = null

    var filterHighestPrice: Double? = null

    var saleableCountryFlag = true

    var needCorrectContent = true

    var brandWrap: SelectableBrandWrap? = null

    val propertyList = arrayListOf<SelectablePropertyWrap>()

    val contentList = arrayListOf<Any>()

    var brandResult = MutableLiveData<BrandVOF>()

    val resultList = arrayListOf<ProductFWrap>()

    val recommendList = arrayListOf<RecommendProductF>()

    val resultLD = MutableLiveData<List<ProductFWrap>?>()

    val recommendLD = MutableLiveData<List<RecommendProductF>?>()

    val drawerDataLD = MutableLiveData<Boolean>()

    val drawerContentList = arrayListOf<Any>()

    val frontPropertyContentList = arrayListOf<Any>()

    val drawerPriceModel = DrawerPriceInputModel()


    var drawerClearClickTag = false

    var drawerDoneClickTag = false

    val emptyModel: GoodsResultEmptyModel by lazyOnNone {
        GoodsResultEmptyModel(emptyTxt2 = string(com.starblink.basic.style.R.string.no_items_found))
    }

    val recTitleModel: GoodsRecommendTileModel by lazyOnNone {
        GoodsRecommendTileModel(string(com.starblink.basic.style.R.string.you_may_like))
    }

    val errWordLiveData = MutableLiveData<String>()

    fun loadErrWordData() {
        needCorrectContent = false
        showLoadDialog()
        loadInitData()
    }

    private fun loadBrandData() {
        viewModelScope.launch {
            val response = SkGqlClient.skQuery(
                SearchBrandsQuery(
                    params = BrandSearchReq(
                        contentSearch = queryWord.optional(),
                        pageNo = 1.optional(),
                        pageSize = 1.optional()
                    )
                )
            )
            val list =
                response?.data?.searchBrands?.map { it.brandVOF } ?: arrayListOf()

            if (!list.isNullOrEmpty()) {
                brandResult.postValue(list.first())
            }
        }
    }

    fun loadInitData() {
        pageNo = 1
        contentList.clear()
        needQueryFilter = true
        saleableCountryFlag = true
        filterLowestPrice = null
        filterHighestPrice = null
        reqFilterBrands.clear()
        reqFilterProperties.clear()
        resultList.clear()
        recommendList.clear()
        propertyList.clear()

        if (frontPropertyContentList.size > 0 && frontPropertyContentList.first() is SelectDiscountProperty) {
        } else {
            frontPropertyContentList.clear()
        }
        drawerContentList.clear()

        brandWrap = null

        viewModelScope.launch {
            var data = querySearch()
            loadBrandData()

            if (data?.searchResultStatus == null || data.searchResultStatus == SearchConfig.ResultConfig.STATUS_OTHER_NO_DATA) {
                recPageNo = 1
                val recData = queryRecommend()
                val list = recData?.fetchRecommendProductCollection?.mapIndexed { index, it ->
                    RecommendProductF(
                        it.productF,
                        index + recommendList.size
                    )
                }?.apply {
                    recommendList.addAll(this)
                }
                resultLD.postValue(null)
                recommendLD.postValue(list)
                loadSuccess()
                hideLoadDialog()
                return@launch
            } else if (data.searchResultStatus == SearchConfig.ResultConfig.STATUS_LOCAL_NO_DATA) {
                saleableCountryFlag = false
                data = querySearch()
            }

            val products =
                data?.productList?.mapIndexedNotNull { index, it -> it?.productF?.toWrap(index + resultList.size) }
                    ?.apply {
                        resultList.addAll(this)
                    }

            data?.brandList?.takeIf { it.isNotEmpty() }?.let {
                val brands =
                    it.map { item -> SelectableBrand(source = item.brandVOF, selected = false) }
                brandWrap = SelectableBrandWrap(brands = brands, select = false)
                frontPropertyContentList.add(brandWrap!!)
            }
            data?.propertyList?.map {
                SelectablePropertyWrap(
                    source = it.propertyTwoVOF,
                    properties = it.propertyTwoVOF.values?.map { text ->
                        SelectableProperty(
                            text = text,
                            selected = false
                        )
                    }.orEmpty(),
                    select = false
                )
            }?.let {
                propertyList.addAll(it)
                frontPropertyContentList.addAll(it)
            }
            initDrawerData()

            resultLD.postValue(products)
            if (products.isNullOrEmpty()) {
                loadNoData()
            } else {
                loadSuccess()
            }

            // filter Sale是否可见
            filterSaleVisibleLiveData.postValue(data?.showSale ?: false)

            data?.correctWord?.takeIf { it.isNotEmpty() }?.run {
                errWordLiveData.postValue(this)
            }

            hideLoadDialog()

        }
    }

    fun loadMore() {
        pageNo++
        needQueryFilter = false
        viewModelScope.launch {
            val data = querySearch()
            val products =
                data?.productList?.mapIndexedNotNull { index, it -> it?.productF?.toWrap(index + resultList.size) }
                    ?.apply {
                        resultList.addAll(this)
                    }
            resultLD.postValue(products)
        }
    }

    /**
     * 加载筛选请求
     */
    fun loadFilterRequest() {
        viewModelScope.launch {
            loadStartProgress()
            needQueryFilter = false
            pageNo = 1
            contentList.clear()
            resultList.clear()
            recommendList.clear()
            val data = querySearch()
            val products =
                data?.productList?.mapIndexedNotNull { index, it -> it?.productF?.toWrap(index + resultList.size) }
            if (products.isNullOrEmpty()) {
                recPageNo = 1
                val recData = queryRecommend()
                val list = recData?.fetchRecommendProductCollection?.mapIndexed { index, it ->
                    RecommendProductF(
                        it.productF,
                        index + recommendList.size
                    )
                }?.apply {
                    recommendList.addAll(this)
                }
                recommendLD.postValue(list)
            } else {
                resultList.addAll(products)
                resultLD.postValue(products)
            }
            filterSaleVisibleLiveData.postValue(data?.showSale ?: false)
            loadHideProgress()
        }
    }

    private suspend fun querySearch(): SearchProductsQuery.SearchGoodsV4? {
        return SkGqlClient.skQuery(
            SearchProductsQuery(
                params = ProductQueryParam(
                    contentSearch = queryWord,
                    pageNo = pageNo,
                    pageSize = PAGE_SIZE,
                    searchScene = scene.optional(),
                    needFilterResultList = needQueryFilter.optional(),
                    sortType = sortType.optional(),
                    needCorrectContent = needCorrectContent.optional(),
                    brands = if (reqFilterBrands.isNotEmpty()) reqFilterBrands.optional() else Optional.Absent,
                    propertyList = if (reqFilterProperties.isNotEmpty()) reqFilterProperties.optional() else Optional.Absent,
                    saleableCountryFlag = saleableCountryFlag.optional(),
                    lowestPrice = if (filterLowestPrice != null) filterLowestPrice.optional() else Optional.absent(),
                    highestPrice = if (filterHighestPrice != null) filterHighestPrice.optional() else Optional.absent(),
                    filterSale = filterSale.optional(),
                    isOffer = filterSale.optional(),
                    goodsRuleId = goodsRuleId.optional()
                )
            ),
//            fetchPolicy = FetchPolicy.CacheOnly
        )?.data?.searchGoodsV4
    }

    val filterGroupVisible: Boolean
        get() = resultList.isNotEmpty() || filterVisible

    val frontPropertyVisible: Boolean
        get() = frontPropertyContentList.isNotEmpty()

    val filterVisible: Boolean
        get() = (brandWrap?.brands?.isNotEmpty() == true || propertyList.isNotEmpty())

    val hasFilterSelect: Boolean
        get() = reqFilterBrands.isNotEmpty() || reqFilterProperties.isNotEmpty() || filterLowestPrice != null || filterHighestPrice != null

    fun buildReqBrandAndProperty() {
        assembleReqBrand()
        assembleProperty()
    }

    private fun assembleProperty() {
        reqFilterProperties.clear()
        propertyList.forEach { model ->
            model.properties.forEach {
                if (it.selected) {
                    reqFilterProperties.add("${model.source.name}:${it.text}")
                }
            }
        }
    }

    private fun assembleReqBrand() {
        reqFilterBrands.clear()
        brandWrap?.brands?.forEach {
            if (it.selected && it.source.name?.isNotEmpty() == true) {
                reqFilterBrands.add(it.source.name!!)
            }
        }
    }

    private fun initDrawerData() {
        drawerContentList.clear()
        drawerContentList.add(DrawerTitleModel(text = ""))
        drawerContentList.add(drawerPriceModel)

        var propertyIndex = 0
        brandWrap?.takeIf { it.brands.isNotEmpty() }?.let {
            it.hasMoreProperty = propertyList.isNotEmpty()
            drawerContentList.add(it)
            propertyIndex++
        }

        drawerContentList.addAll(propertyList.onEach {
            it.drawerDataIndex = propertyIndex++
        })

        drawerDataLD.postValue(drawerContentList.isNotEmpty())

    }

    /**
     * 更新抽屉数据
     */
    fun refreshDrawerData() {
        drawerPriceModel.min = filterLowestPrice
        drawerPriceModel.max = filterHighestPrice
        brandWrap?.initCache()
        propertyList.forEach {
            it.initCache()
        }
    }

    /**
     * 从抽屉数据中同步筛选的数据
     */
    fun loadFromDrawerData() {
        filterLowestPrice = drawerPriceModel.min
        filterHighestPrice = drawerPriceModel.max
        brandWrap?.loadSelect2Data()
        propertyList.forEach {
            it.loadSelect2Data()
        }
    }

    fun clearDrawerData() {
        filterLowestPrice = null
        filterHighestPrice = null
        drawerPriceModel.min = null
        drawerPriceModel.max = null
        brandWrap?.run {
            selectCache.clear()
            brands.forEach {
                it.selected = false
            }
        }
        propertyList.forEach { it ->
            it.selectCache.clear()
            it.properties.forEach {
                it.selected = false
            }
        }
    }

    fun loadMoreForU() {
        recPageNo++
        viewModelScope.launch {
            val data = queryRecommend()
            val products = data?.fetchRecommendProductCollection?.mapIndexed { index, it ->
                RecommendProductF(
                    it.productF,
                    index + recommendList.size
                )
            }?.apply {
                recommendList.addAll(this)
            }
            recommendLD.postValue(products)
        }
    }

    private suspend fun queryRecommend(): FetchRecommendProductCollectionQuery.Data? {
        return SkGqlClient.skQuery(
            FetchRecommendProductCollectionQuery(
                params = ProductRecommendQueryParam(
                    sceneCode = 23, // 推荐场景编码 2 首页商品卡片HOME_GOODS_CARD 4 搜索后商品卡片SEARCH_GOODS_CARD 14 商品搜索无结果推荐场景 SEARCH_PAGE_MIGHT_LIKE
                    contentSearch = queryWord.optional(),
                    pageNo = recPageNo,
                    pageSize = PAGE_SIZE,
                )
            )
        )?.data
    }

    fun setEmptyText() {
        emptyModel.emptyTxt2 = emptyString
    }

    fun addDiscountItem(filterSale: Boolean) {
        if (filterSale) {
            if (frontPropertyContentList.size > 0 && frontPropertyContentList.first() is SelectDiscountProperty) {
                return
            }
            frontPropertyContentList.add(0, SelectDiscountProperty(SearchConfig.SORT_DEFAULT))
        } else {
            if (frontPropertyContentList.size > 0 && frontPropertyContentList.first() is SelectDiscountProperty) {
                frontPropertyContentList.removeAt(0)
            }
        }
    }

    val emptyString: String
        get() = string(
            when {
                hasFilterSelect -> com.starblink.basic.style.R.string.search_empty_tip3
                !saleableCountryFlag -> com.starblink.basic.style.R.string.search_empty_tip3
                else -> com.starblink.basic.style.R.string.no_items_found
            }
        )


    companion object {

        const val PAGE_SIZE = 20
    }


}